package com.yupi.yuoj.judge;

import cn.hutool.json.JSONUtil;
import com.yupi.yuoj.common.ErrorCode;
import com.yupi.yuoj.exception.BusinessException;
import com.yupi.yuoj.judge.codesandbox.CodeSandboxFactory;
import com.yupi.yuoj.judge.codesandbox.CodeSandboxProxy;
import com.yupi.yuoj.judge.codesandbox.model.ExecuteCodeRequest;
import com.yupi.yuoj.judge.codesandbox.model.ExecuteCodeResponse;
import com.yupi.yuoj.judge.codesandbox.strategy.DefaultJudgeStrategy;
import com.yupi.yuoj.judge.codesandbox.strategy.JudgeContext;
import com.yupi.yuoj.judge.codesandbox.strategy.JudgeStrategy;
import com.yupi.yuoj.model.dto.question.JudgeCase;
import com.yupi.yuoj.judge.codesandbox.model.JudgeInfo;
import com.yupi.yuoj.model.entity.Question;
import com.yupi.yuoj.model.entity.QuestionSubmit;
import com.yupi.yuoj.model.enums.QuestionSubmitStatusEnum;
import com.yupi.yuoj.service.QuestionService;
import com.yupi.yuoj.service.QuestionSubmitService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author hch
 * @version 1.0
 * @description 判题逻辑
 * @date 2024/6/25 16:48
 */
@Service
@Slf4j
public class JudgeServiceImpl implements JudgeService {

    @Resource
    private QuestionSubmitService questionSubmitService;

    @Resource
    private QuestionService questionService;

    @Value("${codesandbox.type:example}")
    private String type;

    @Resource
    private JudgeManager judgeManager;


    @Override
    public QuestionSubmit doJudge(Long questionSubmitId) {
        if (questionSubmitId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空");
        }
        //获取题目提交信息
        QuestionSubmit questionSubmit = questionSubmitService.getById(questionSubmitId);
        //进行信息合法判断
        if (questionSubmit == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "没有提交该题目");
        }
        String language = questionSubmit.getLanguage();
        String code = questionSubmit.getCode();
        Long questionId = questionSubmit.getQuestionId();
        //获取题目信息
        Question question = questionService.getById(questionId);
        if (question == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "题目为空");
        }

        //判断一下状态是否为等待状态
        if (!questionSubmit.getStatus().equals(QuestionSubmitStatusEnum.WAITING.getValue())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "题目正在判题中");
        }
        QuestionSubmit submit = new QuestionSubmit();
        submit.setId(questionSubmitId);
        //设置当前题目的状态为判题中
        submit.setStatus(QuestionSubmitStatusEnum.RUNNING.getValue());
        boolean count = questionSubmitService.updateById(submit);
        if (!count) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "题目状态更新错误");
        }

        String judgeCase = question.getJudgeCase();
        List<JudgeCase> judgeCases = JSONUtil.toList(judgeCase, JudgeCase.class);
        String judgeConfig = question.getJudgeConfig();
        String answer = question.getAnswer();
        //创建代理对象
        CodeSandboxProxy codeSandboxProxy = new CodeSandboxProxy(CodeSandboxFactory.newInstance(type));
        ExecuteCodeRequest<Object> request = new ExecuteCodeRequest<>();
        request.setCode(code);
        request.setLanguage(language);
        //获取输入用例
        List<String> input = judgeCases.stream().map(item -> {
            return item.getInput();
        }).collect(Collectors.toList());
        request.setInputList(input);
        //调用代码沙箱
        ExecuteCodeResponse executeCodeResponse = codeSandboxProxy.executeCode(request);
        List<String> outputList = executeCodeResponse.getOutputList();
        JudgeInfo judgeInfo = executeCodeResponse.getJudgeInfo();
        JudgeStrategy judgeStrategy = new DefaultJudgeStrategy();
        JudgeContext judgeContext = new JudgeContext();
        judgeContext.setJudgeInfo(judgeInfo);
        judgeContext.setInputList(input);
        judgeContext.setOutputList(outputList);
        judgeContext.setQuestion(question);
        judgeContext.setQuestionSubmit(questionSubmit);

        JudgeInfo info = judgeManager.doJudge(judgeContext);
        log.info("info为:{}", info);
        String infoStr = JSONUtil.toJsonStr(info);
        submit = new QuestionSubmit();
        submit.setJudgeInfo(infoStr);
        submit.setId(questionSubmitId);
        //设置当前题目的状态为判题中
        submit.setStatus(QuestionSubmitStatusEnum.SUCCESS.getValue());
        count = questionSubmitService.updateById(submit);
        if (!count) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "题目状态更新错误");
        }
        //去数据库中查一下
        QuestionSubmit ResultQuestionSubmit = questionSubmitService.getById(questionSubmitId);


        return ResultQuestionSubmit;
    }
}
